﻿using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Effects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using 纸片人.AttributeUsageFloder;
using 纸片人.InfoDataFolder;

// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板

namespace 纸片人.GpuPage
{
    public enum Brushs
    {
        普通,
        晶格
    }

    [PageType("gpu", "置换旋转")]
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public partial class DisplacementDistortionPage : Page
    {

        #region SelectBrushs     
        /// <summary>
        /// 获取或设置SelectBrushs的值
        /// </summary>  
        public Brushs SelectBrushs
        {
            get { return (Brushs)GetValue(SelectBrushsProperty); }
            set
            {
                if (value == SelectBrushs)
                    return;
                SetValue(SelectBrushsProperty, value);
            }
        }

        /// <summary>
        /// 标识 SelectBrushs 依赖属性。
        /// </summary>
        public static readonly DependencyProperty SelectBrushsProperty =
            DependencyProperty.Register("SelectBrushs", typeof(Brushs), typeof(DisplacementDistortionPage), new PropertyMetadata(Brushs.普通, OnSelectBrushsChanged));

        private static void OnSelectBrushsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            DisplacementDistortionPage target = obj as DisplacementDistortionPage;
            Brushs oldValue = (Brushs)args.OldValue;
            Brushs newValue = (Brushs)args.NewValue;
            if (oldValue != newValue)
                target.OnSelectBrushsChanged(oldValue, newValue);
        }

        protected virtual void OnSelectBrushsChanged(Brushs oldValue, Brushs newValue)
        {
            selectBrush = newValue;
        }
        #endregion


        CanvasRenderTarget renderTarget;
        CanvasRenderTarget tempTarget;

        Brushs selectBrush;

        Vector2 pos;
        float radius = 30;
        //是否进入来了
        bool isEntry;

        float effectWidth = 0;
        float effectHeight = 0;
        float previewWidth = 0;
        float previewHeight = 0;
        float offsetX, offsetY, scale, width, height;

        //是否按下
        bool isPressed;

        public DisplacementDistortionPage()
        {
            this.InitializeComponent();
            Init();
        }
        LayerBitmapData bitmapData = new LayerBitmapData();
        private CanvasRenderTarget mappingBitmap;

        CanvasDevice device;
        private void Init()
        {
            List<Brushs> brush = new List<Brushs>();
            foreach (Brushs item in Enum.GetValues(typeof(Brushs)))
            {
                brush.Add(item);
            }
            brushCombo.ItemsSource = brush;

            //选择图片
            selectPicture.Click += async (s, e) =>
            {
                await bitmapData.SelectOneBitmapAsync(canvas.Device);
                if (bitmapData.oneBitmap != null)
                {
                    CalcuationPosition();
                    renderTarget = new CanvasRenderTarget(canvas, bitmapData.oneBitmap.Size);
                    mappingBitmap = new CanvasRenderTarget(canvas, bitmapData.oneBitmap.Size);
                    DrawMapping();
                    using (var ds = renderTarget.CreateDrawingSession())
                    {
                        ds.DrawImage(bitmapData.oneBitmap);
                    }
                    tempTarget = new CanvasRenderTarget(canvas, bitmapData.oneBitmap.Size);
                }
            };
            //绘制
            Action DrawDistortion = () =>
            {
                if (!isPressed)
                    return;
                using (var ds = tempTarget.CreateDrawingSession())
                {
                    ds.Clear(Colors.Transparent);
                    ds.DrawImage(renderTarget);
                }



                using (var ds = mappingBitmap.CreateDrawingSession())
                {
                    //["position"]= (pos - new Vector2(offsetX, offsetY)) / scale,
                    //    ["radius"]= radius,
                    var center = (pos - new Vector2(offsetX, offsetY)) / scale;

                    switch (selectBrush)
                    {
                        case Brushs.普通:
                            ds.FillCircle(center, radius, new CanvasRadialGradientBrush(device, Color.FromArgb(255, 1, 1, 255), Colors.Transparent)
                            {
                                Center = center,
                                RadiusX = radius,
                                RadiusY = radius,
                                Opacity = 0.4f,
                            });
                            break;
                        case Brushs.晶格:
                            if (bitmapData.oneShaderCode != null)
                            {
                                PixelShaderEffect lattice = new PixelShaderEffect(bitmapData.oneShaderCode)
                                {
                                    Properties = { ["size"] = radius * 2 }
                                };

                                ds.DrawImage(lattice, center - new Vector2(radius));
                            }
                            break;
                        default:
                            break;
                    }


                }

                using (var ds = renderTarget.CreateDrawingSession())
                {
                    ds.DrawImage(new DisplacementMapEffect
                    {
                        Source = bitmapData.oneBitmap,
                        Displacement = mappingBitmap,
                        XChannelSelect = EffectChannelSelect.Red,
                        YChannelSelect = EffectChannelSelect.Green,
                        Amount = 100,
                    });
                }

            };
            //创建资源
            canvas.CreateResources += (s, e) =>
            {
                device = s.Device;
                e.TrackAsyncAction(bitmapData.LoadOneShadeCodeAsync(Shaders.ShaderType.LatticeBrush).AsAsyncAction());
            };
            //画板绘制
            canvas.Draw += (s, e) =>
            {
                Function.DrawGridGraphics(e.DrawingSession);

                if (renderTarget != null)
                {
                    var previewTran = Function.CalcutateImageCenteredTransform(previewWidth, previewHeight, bitmapData.oneWidth, bitmapData.oneHeight);
                    previewTran.Source = bitmapData.oneBitmap;
                    e.DrawingSession.DrawImage(previewTran, 0, effectHeight);

                    if (mappingBitmap != null)
                    {
                        var mappingTran = Function.CalcutateImageCenteredTransform(previewWidth, previewHeight, bitmapData.oneWidth, bitmapData.oneHeight);
                        mappingTran.Source = mappingBitmap;
                        e.DrawingSession.DrawImage(mappingTran, previewWidth, effectHeight);
                    }


                    var effectTran = Function.CalcutateImageCenteredTransform(effectWidth, effectHeight, bitmapData.oneWidth, bitmapData.oneHeight);
                    effectTran.Source = renderTarget;
                    e.DrawingSession.DrawImage(effectTran);



                    //是否进入范围
                    if (isEntry && (pos.X >= offsetX && pos.X <= offsetX + width && pos.Y >= offsetY && pos.Y <= offsetY + height))
                    {
                        DrawDistortion();
                        e.DrawingSession.DrawCircle(pos, radius * scale, Colors.Black, 4f);
                        e.DrawingSession.DrawCircle(pos, radius * scale, Colors.White, 2f);
                    }
                }
            };
            //进入
            canvas.PointerEntered += (s, e) =>
            {
                isEntry = true;
            };
            //离开
            canvas.PointerExited += (s, e) =>
            {
                isEntry = false;
            };
            //移动
            canvas.PointerMoved += (s, e) =>
            {
                pos = e.GetCurrentPoint(canvas).Position.ToVector2();
                CalcuationPosition();
            };
            //按下
            canvas.PointerPressed += (s, e) =>
            {
                isPressed = true;
                canvas.Invalidate();
            };
            //松开
            canvas.PointerReleased += (s, e) =>
            {
                isPressed = false;
                bitmapData.oneBitmap.CopyPixelsFromBitmap(renderTarget);
                DrawMapping();

            };
            //改变半径
            radiusSlider.ValueChanged += (s, e) =>
            {
                radius = (float)radiusSlider.Value * Math.Max(bitmapData.oneWidth, bitmapData.oneHeight) / 2f;

            };
            //大小更改
            canvas.SizeChanged += (s, e) =>
            {
                CalcuationPosition();
            };
            //重置
            reset.Click += (s, e) =>
            {
                if (bitmapData.oneBitmap != null && renderTarget != null)
                {
                    using (var ds = renderTarget.CreateDrawingSession())
                    {
                        ds.Clear(Colors.Transparent);
                        ds.DrawImage(bitmapData.oneBitmap);
                    }
                }
            };
        }

        bool clearing = false;
        /// <summary>
        /// 绘制法线图
        /// </summary>
        void DrawMapping()
        {
            if (mappingBitmap == null &&clearing)
                return;
            if (!clearing)
            {
                clearing = true;
                using (var ds = mappingBitmap.CreateDrawingSession())
                {
                    ds.Clear(Colors.Transparent);
                    ds.FillRectangle(new Rect(0, 0, bitmapData.oneWidth, bitmapData.oneHeight), Color.FromArgb(255, 128, 128, 255));
                }
                clearing = false;
            }
        }

        void CalcuationPosition()
        {
            if (bitmapData.oneBitmap == null)
                return;

            radius = (float)radiusSlider.Value * Math.Max(bitmapData.oneWidth, bitmapData.oneHeight) / 2f;

            var element = canvas;
            effectWidth = (float)element.ActualWidth;
            effectHeight = (float)element.ActualHeight * 0.7f;
            previewWidth = effectWidth * 0.5f;
            previewHeight = (float)element.ActualHeight * 0.3f;

            var mat = Function.CalcutateImageCenteredMat(effectWidth, effectHeight, bitmapData.oneWidth, bitmapData.oneHeight);
            scale = mat.M11;
            offsetX = mat.M31;
            offsetY = mat.M32;
            width = scale * bitmapData.oneWidth;
            height = scale * bitmapData.oneHeight;
        }
    }
}
